/**
 * Copyright 2006 gworks.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 */
package org.javaongems.server.rpc.util;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.javaongems.client.service.ResourceBundleRpc;
import org.javaongems.server.GemServe;

/**
 * <p>Provides the implementation of a resource bundle service.</p>
 * @author Ashin Wimalajeewa (ash)
 */
public class ResourceBundleRpcImpl implements ResourceBundleRpc {
	final static public String GEM_BUNDLE_LOCALE = "gem-bundle-locale";
	final static HashMap bundles = new HashMap();
	
	public Map getResourceBundle(String name) 
			throws MissingResourceException {
		Locale locale = getSessionsLocaleAttribute();
		return getResourceBundle(name, locale);
	}

	public Map getResourceBundle(String name, LocaleInfo localeInfo) 
			throws MissingResourceException {
		Locale locale = null;
		if (localeInfo == LocaleInfo.HTTP_REQUEST_LOCALE)
			locale = getSessionsLocaleAttribute();
		else
			locale = toLocale(localeInfo);
		return getResourceBundle(name, locale);
	}
	
	private Map getResourceBundle(String name, Locale locale) 
			throws MissingResourceException {
		try {
			String key = bundleHashCode(name, locale);
			HashMap ret = (HashMap) bundles.get(key);
			if (ret == null) {
				ResourceBundle rb = ResourceBundle.getBundle(name, locale);
				ret = toHashMap(rb);
				bundles.put(key, ret);
			}
			return ret;
		} catch (java.util.MissingResourceException err) {
			throw new MissingResourceException(err.getMessage(), err.getClassName(), err.getKey());
		}
	}

	public LocaleInfo getSessionsLocale() {
		Locale sessLocale = getSessionsLocaleAttribute();
		return toRpcLocale(sessLocale);
	}

	public void setSessionsLocale(LocaleInfo locale) {
		HttpSession session = getHttpServletRequest().getSession();
		Locale toSet = new Locale(locale.language, locale.country, locale.variant);
		session.setAttribute(GEM_BUNDLE_LOCALE, toSet);
	}
	
	private Locale getSessionsLocaleAttribute() {
		HttpServletRequest request = getHttpServletRequest();
		HttpSession session = request.getSession();
		Locale locale = (Locale) session.getAttribute(GEM_BUNDLE_LOCALE);
		if (locale == null) {
			locale = request.getLocale();
			setSessionsLocaleAttribute(session, locale);
		}
		return locale;
	}

	private void setSessionsLocaleAttribute(HttpSession session, Locale locale) {
		session.setAttribute(GEM_BUNDLE_LOCALE, locale);	
	}
	
	private LocaleInfo toRpcLocale(Locale locale) {
		return new LocaleInfo(locale.getLanguage(), locale.getCountry(), locale.getVariant());
	}
	
	private Locale toLocale(LocaleInfo locale) {
		return new Locale(locale.language, locale.country, locale.variant);
	}
	
	private HttpServletRequest getHttpServletRequest() {
		return GemServe.getThreadLocalHttpServletRequest();
	}
	
	static private HashMap toHashMap(ResourceBundle rb) {
		HashMap ret = new HashMap();
		Enumeration keys = rb.getKeys();
		while (keys.hasMoreElements()) {
			String key = (String) keys.nextElement();
			String val = rb.getString(key);
			ret.put(key, val);
		}
		return ret;
	}
	
	static private String bundleHashCode(String name, Locale locale) {
		String hc = name.hashCode() + "::" + locale.hashCode();
		return hc;
	}
}